查看原文
其他

从Oracle到PostgreSQL:一文掌握Checkpoint重要概念

钟浪峰 数据和云 2024-03-03

墨墨导读:Checkpoint是数据库中重要的概念,无论在Oracle,MySQL这个概念,它主要功能是在检查点时刻,脏数据全部刷新到磁盘,以实现数据的一致性和完整性。PostgreSQL为什么要设计Checkpoint呢?跟Oracle一样,其主要目的是缩短崩溃恢复时间。PostgreSQL在崩溃恢复时会以最近的Checkpoint为基础,不断应用这之后的WAL日志。下面我们就从Oracle的角度去学习下PostgreSQL的Checkpoint。



PG检查点进程



Oracle的checkpoint进程是由单独的ckpt进程负责的,PostgreSQL也一样,有专门的checkpoint进程checkpointer,它由postmaster负责创建。作为postmaster的子进程而存在,为几大重要的后台进程之一。


从下图中,可知postmaster进程号为1962。checkpoint的进程号为1965,其父进程号为1962,即为



Kill检查点进程可以如下图可以看到,其他进程也跟着checkoint进程重启了。有点类似于系统被初始化后。可见此进程对数据一致保护的重要性。




PG检查点的类型



在xlog.h文件中,有如下代码对checkpoint进行了相应的分类:    


/* These directly affect the behavior of CreateCheckPoint and subsidiaries */#define CHECKPOINT_IS_SHUTDOWN 0x0001 /* Checkpoint is for shutdown */#define CHECKPOINT_END_OF_RECOVERY 0x0002 /* Like shutdown checkpoint, but                                                                                         * issued at end of WAL recovery */ #define CHECKPOINT_IMMEDIATE 0x0004 /* Do it without delays */#define CHECKPOINT_FORCE 0x0008 /* Force even if no activity */#define CHECKPOINT_FLUSH_ALL 0x0010 /* Flush all pages, including those * belonging to unlogged tables *//* These are important to RequestCheckpoint */#define CHECKPOINT_WAIT 0x0020 /* Wait for completion *//* These indicate the cause of a checkpoint request */#define CHECKPOINT_CAUSE_XLOG 0x0040 /* XLOG consumption */#define CHECKPOINT_CAUSE_TIME   0x0080  /* Elapsed time */                                                                                        

                   

  1. CHECKPOINT_IS_SHUTDOWN(shutdown检查点):在PG实例shutdown时做的检点

  2. CHECKPOINT_END_OF_RECOVERY(recovery end检查点): 在recovery 结束阶段做的检查点,类似于shutdown检查点,只不过在WAL恢复结束时发起。

  3. CHECKPOINT_IMMEDIATE(immediate检查点):不仅仅创建检查点,而且会马上做。这类请求一般在比较紧急的情况下,需要马上获取数据库一致状态的情况下。

  4. CHECKPOINT_FORCE(force检查点):即使没有xlog变更,也会做。请求这类检查点,往往只是想得到最近的checkpoint location而已。

  5. CHECKPOINT_FLUSH_ALL(flush检查点): 当发起flush 所有pages时发起,包括那些不logging的表

  6. CHECKPOINT_WAIT (wait检查点):检查点不会马上做,但会一直等待,直到检查点完成。往往比较重要的一些操作,但不是非常紧急的,可以请求该类检查点。尤其是一些DDL操作,对数据一致性要求高于响应时间。

  7. CHECKPOINT_CAUSE_XLOG(xlog检查点):由xlog的消耗引起,产生新xlog文件。

  8. CHECKPOINT_CAUSE_TIME (time检查点):由时间elapse引起。

从上可知,PostgreSQL的checkpoint类型也很丰富,但是它比oracle的类型少些,比如增量checkpoint.



Checkpoint触发条件



以下几种情况会触发数据库操作系统做检查点操作:


1) 超级用户(其他用户不可)执行checkpoint命令


2) 数据库shutdown


3) 数据库recovery完成


4) WAL日志量达到了触发checkpoint阈值


5) 周期性地进行checkpoint


6) 需要刷新所有脏页



checkpoint调优



如何设置调优checkpoint,设置正确的参数呢?首先我们要先了解PostgreSQL数据的同步机制。

PostgreSQL数据的同步机制


 图1. 数据同步机制


整个同步机制如上图1所示。数据库的后台进程在执行用户事务时,发生的数据更改是先写入缓冲池中,对应PostgreSQL就是shared buffers。PostgreSQL的缓冲池一般设置为总内存的1/4左右,缓冲池里面的这些数据更改,在事务提交时,是无需同步写入到磁盘的。因为在事务提交时,会先写入WAL日志,有了WAL日志,就可以在异常情况下将数据恢复,保障数据安全,因此数据本身是否在提交时写入磁盘就没那么重要了。PostgreSQL是只是在需要的时候,例如脏页较多时、或一定时间间隔后,才将数据写回磁盘。


脏页处理的过程分为几个步骤。首先是由background writer将shared buffers里面的被更改过的页面(即脏页),通过调用write写入操作系统page cache。在函数BgBufferSync可以看到,PostgreSQL的background writer进程,会根据LRU链表,扫描shared buffers(实际上是每次扫描一部分),如果发现脏页,就调用系统调用write。可以通过设置bgwriter_delay参数,来控制background writer每次扫描之间的时间间隔。background writer在对一个页面调用write后,会将该页面对应的文件(实际上是表的segement,每个表可能有多个segment,对应多个物理文件)记录到共享内存的数组CheckpointerShmem->requests中,调用顺序如下:

BackgroundWriterMain -> BgBufferSync -> SyncOneBuffer -> FlushBuffer -> smgrwrite->mdwrite-> dirty_segment-> register-> ForwardFsyncRequest


这些request最终会被checkpointer进程读取,放入pendingOpsTable,而真正将脏页回写到磁盘的操作,是由checkpointer进程完成的。checkpointer每次也会调用smgrwrite,把所有的shared buffers脏页(即还没有被background writer清理过得脏页)写入操作系统的page cache,并存入pendingOpsTable。这样pendingOpsTable存放了所有write过的脏页,包括之前background writer已经处理的脏页。随后PostgreSQL的checkpointer进程会根据pedingOpsTable的记录,进行脏页回写操作(注意每次调用fysnc,都会sync数据表的一个文件,文件中所有脏页都会写入磁盘),调用顺序如下:

CheckPointGuts->CheckPointBuffers->->mdsync->pg_fsync->fsync


如果checkpointer做磁盘写入的频率过高,则每次可能只写入很少的数据。我们知道,磁盘对于顺序写入批量数据比随机写的效率要高的多,每次写入很少数据,就造成大量随机写;而如果我们放慢checkpoint的频率,多个随机页面就有可能组成一次顺序批量写入,效率大大提高。另外,checkpoint会进行fsync操作,大量的fsync可能造成系统IO阻塞,降低系统稳定性,因此checkpoint不能过于频繁。但checkpoint的间隔也不能无限制放大。因为如果出现系统宕机,在进行恢复时,需要从上一次checkpoint的时间点开始恢复,如果checkpoint间隔过长,会造成恢复时间缓慢,降低可用性。


相关参数配置


checkpoint_warning  

如果检查点触发的频率小于30s,则log日志中会提醒你增加max_wal_size。

  • 参考设置:如果硬盘的性能很好可以设置小一些,如果硬盘性能差就设置大一些。这个参数不影响性能。只是用来检查实际checkpoint发生的频率。


checkpoint_timeout

自动检查点出发的时间,增加这个参数的值会增加崩溃恢复所需的时间。取值范围为30S≈1天。磁盘性能好的话可以适当减小。这个值减小会增加检查点频率,降低性能。

 

max_wal_size 

在自动WAL检查点使得WAL增长到最大尺寸,到了这个尺寸,检查点就开始工作。

  • 参考值:主机内存1/2,默认是1GB


min_wal_size

WAL磁盘使用率低于这个设置,旧的WAL文件总数被回收,确保预留足够的WAL空间处理WAL使用中的峰值。

  • 参考值:主机内存1/8


checkpoint_completion_target

指定检查点完成的目标,作为检查点之间总时间的一部分。默认值是0.5,这个参数一般要结合checkpoint_timeout来使用。


场景

数据量

数据写入速度(1G/s

checkpoint_completion_target=0.5

checkpoint_timeout = 30min

100G 

100/(0.5*30*60)*1024≈114M/s

checkpoint_completion_target=0.9

checkpoint_timeout = 30min

100G 

100/(0.8*30*60)*1024≈71M/s


从上可知checkpoint_completion_target设置的越高的情况下,写入速度越低,对客户而言,体验越好,性能越高。反之,较低的值可能会引起I/O峰值,导致“卡死”的现象。


  • 考值:0.8≈0.9


checkpoint_flush_after

单位:BLCKSZ

当checkpointer process脏数据超过配置阈值时,触发调用OS sync_file_range,告诉os backend flush线程异步刷盘。从而削减os dirty page堆积

  • 参考值:有效范围介于0(禁用强制写回)和2MB之间。Linux上的默认值为256KB,其他地方为0


扩展阅读



  1. 《PostgreSQL 指南:内幕探索》之基础备份与时间点恢复(上)

  2. 《PostgreSQL 指南:内幕探索》之基础备份与时间点恢复(下)

  3. 解读年度数据库PostgreSQL:如何处理并发控制(一)

  4. “王者对战”之 MySQL 8 vs PostgreSQL 10

  5. 大象起舞:用PostgreSQL解海盗分金问题

  6. 解读年度数据库PostgreSQL:如何巧妙地实现缓冲区管理器

  7. 解读年度数据库PostgreSQL:如何处理并发控制(一)

  8. 数据和云,半年文章精选(文末赠书)

  9. 美女DBA带你了解PostgreSQL用户及角色

  10. 从Oracle到PostgreSQL:最全控制文件




数据和云

ID:OraNews

如有收获,请划至底部,点击“在看”,谢谢!


资源下载

关注公众号:数据和云(OraNews)回复关键字获取

help,30万+下载的完整菜单栏

2019DTCC,数据库大会PPT

2018DTCC , 数据库大会PPT

2018DTC,2018 DTC 大会 PPT

ENMOBK《Oracle性能优化与诊断案例》

DBALIFE,“DBA 的一天”海报

DBA04,DBA 手记4 电子书

122ARCH,Oracle 12.2体系结构图

2018OOW,Oracle OpenWorld 资料

产品推荐

云和恩墨Bethune Pro2 企业版,集监控、巡检、安全于一身,你的专属数据库实时监控和智能巡检平台,漂亮的不像实力派,你值得拥有!



云和恩墨zData一体机现已发布超融合版本和精简版,支持各种简化场景部署,零数据丢失备份一体机ZDBM也已发布,欢迎关注。


云和恩墨大讲堂 | 一个分享交流的地方

长按,识别二维码,加入万人交流社群


请备注:云和恩墨大讲堂

继续滑动看下一个

从Oracle到PostgreSQL:一文掌握Checkpoint重要概念

钟浪峰 数据和云
向上滑动看下一个

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存